import log4js from 'log4js'
const logConfig = require('../config/logger');
import {KoaMiddlewareInterface,Middleware} from "routing-controllers";

// 加载配置文件
log4js.configure(logConfig);

@Middleware({ type: "after" })
export class log4Middleware implements KoaMiddlewareInterface { // interface implementation is optional
// 调用预先定义的日志名称
   resLogger = log4js.getLogger('resLogger');
   reqLogger = log4js.getLogger('http');
   errorLogger = log4js.getLogger('errorLogger');
   consoleLogger = log4js.getLogger();
  constructor(){

  }

  async use(ctx: any, next: (err?: any) => Promise<any>): Promise<any> {
    this.reqLog(ctx, 0)
    const start: number = new Date().getMilliseconds();
    let ms: number = new Date().getMilliseconds() - start;
    await next();
    try {
      // 开始进入到下一个中间件
      if (ctx.status === 404) {
        ctx.throw(404);
      }
      ms = new Date().getMilliseconds() - start;
      // 记录响应日志
      this.logResponse(ctx, ms);
    } catch (error) {
      ms = new Date().getMilliseconds() - start;
      // 记录异常日志
      this.logError(ctx, error, ms);
    }

  }

  // 封装错误日志
  logError(ctx:any, error:any, resTime:number) {
    if (ctx && error) {
      this.errorLogger.error(this.formatError(ctx, error, resTime));
    }
  };

// 封装请求日志
  reqLog(ctx:any, resTime:number) {
    if (ctx) {
      this.reqLogger.info(this.formatReqLog(ctx, resTime));
    }
  };

// 封装响应日志
  logResponse(ctx:any, resTime:number) {
    if (ctx) {
      this.resLogger.info(this.formatRes(ctx, resTime));
    }
  };

  logInfo(info:object) {
    if (info) {
      this.consoleLogger.info(this.formatInfo(info));
    }
  };

  formatInfo(info:object) {
    let logText = '';
    // 响应日志开始
    logText += '\n' + '***************info log start ***************' + '\n';

    // 响应内容
    logText += 'info detail: ' + '\n' + JSON.stringify(info) + '\n';

    // 响应日志结束
    logText += '*************** info log end ***************' + '\n';

    return logText;
  };

// 格式化响应日志
  formatRes(ctx:any, resTime:number) {
    let logText = '';
    // 响应日志开始
    logText += '\n' + '*************** response log start ***************' + '\n';

    // 添加请求日志
    logText += this.formatReqLog(ctx.request, resTime);

    // 响应状态码
    logText += 'response status: ' + ctx.status + '\n';

    // 响应内容
    logText += 'response body: ' + '\n' + JSON.stringify(ctx.body) + '\n';

    // 响应日志结束
    logText += '*************** response log end ***************' + '\n';

    return logText;
  }

// 格式化错误日志
  formatError(ctx:any, err:any, resTime:number) {
    let logText = '';

    // 错误信息开始
    logText += '\n' + '*************** error log start ***************' + '\n';

    // 添加请求日志
    logText += this.formatReqLog(ctx.request, resTime);

    // 错误名称
    logText += 'err name: ' + err.name + '\n';
    // 错误信息
    logText += 'err message: ' + err.message + '\n';
    // 错误详情
    logText += 'err stack: ' + err.stack + '\n';

    // 错误信息结束
    logText += '*************** error log end ***************' + '\n';

    return logText;
  }

// 格式化请求日志
  formatReqLog(req:any, resTime:number) {
    let logText = '';

    let method = req.method;
    // 访问方法
    logText += '\n' + 'request method: ' + method + '\n';

    // 请求原始地址
    logText += 'request originalUrl:  ' + req.originalUrl + '\n';

    // 客户端ip
    logText += 'request client ip:  ' + req.ip + '\n';

    // 开始时间
    //   var startTime;
    // 请求参数
    if (method === 'GET') {
      logText += 'request query:  ' + JSON.stringify(req.query) + '\n';
      // startTime = req.query.requestStartTime;
    } else {
      logText += 'request body: ' + '\n' + JSON.stringify(req.body) + '\n';
      // startTime = req.body.requestStartTime;
    }
    // 服务器响应时间
    logText += 'response time: ' + resTime + '\n';

    return logText;
  }

}
